package MyGui;

import java.awt.*;
import java.awt.event.*;
import java.io.File;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.filechooser.FileFilter;
import javax.swing.table.*;
import java.text.NumberFormat;
import java.util.Vector;

import DistSys.*;
import Element.AbsElem;
import Element.Geom.AbsElemGeom;

public class OptionsDlg extends MyDlgFrame implements ActionListener,
                                                      WindowListener {
    private JTabbedPane tabbedPane;
    private JButton     btnOk, btnCancel;
    private int         iBlockUpdate = 0;

    // tab "Zone Display"
    private Vector         vZoneData;
    private ZoneTableModel modelZone;
    private JTable         tblZone;
    private JButton        btnRemoveZones;
    private JButton        btnRefreshScreen;
    private JButton        btnZoneUp;
    private JButton        btnZoneDown;

    // tab "Zone Buffers"

    // tab "Paths"
    private PathsPanel tabPaths;

    // tab "Project"

    // tab "Scale"
    private JTextField tfGridSpacing;
    private JRadioButton[] rbs;
    private JTextField tfScale;
    private JButton btnAccept;

    // tab "Status Bar"

    // tab "Misc"
    private JComboBox comboLookAndFeel;

    public static final int TAB_DEFAULT      = -1;
    public static final int TAB_FIRST        =  0;
    public static final int TAB_ZONE_DISPLAY =  0;
    public static final int TAB_PATHS        =  1;
    public static final int TAB_SCALE        =  2;
    //public static final int TAB_ZONE_BUFFER  =  3;
    //public static final int TAB_PROJECT      =  4;
    //public static final int TAB_STATUS_BAR   =  5;
    //public static final int TAB_MISC         =  6;

    public OptionsDlg(MainFrame parent, String title, int initialTab) {
        super(parent, title);

        tabbedPane = new JTabbedPane();
        tabbedPane.addTab("Zone Display", createTabZoneDisplay());
        tabPaths = new PathsPanel();
        tabbedPane.addTab("Paths",        tabPaths);
        tabbedPane.addTab("Scale",        createTabScale());
        //tabbedPane.addTab("Zone Buffers", createTabZoneBuffers());
        //tabbedPane.addTab("Project",      createTabProject());
        //tabbedPane.addTab("Status Bar",   createTabStatusBar());
        //if (SysConst.DEBUG_MODE >= 2)
        //    tabbedPane.addTab("Misc",         createTabMisc());

        if (initialTab != TAB_DEFAULT)
            tabbedPane.setSelectedIndex(initialTab);

        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        btnOk = new JButton("Ok");
        btnOk.addActionListener(this);
        buttonPanel.add(btnOk);
        btnCancel = new JButton("Cancel");
        btnCancel.addActionListener(this);
        buttonPanel.add(btnCancel);
        getRootPane().setDefaultButton(btnOk);

        this.getContentPane().setLayout(new BorderLayout(GAP, GAP));
        this.getContentPane().add(tabbedPane, BorderLayout.CENTER);
        this.getContentPane().add(buttonPanel, BorderLayout.SOUTH);

        this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        this.setLocation(200,200);
        this.setSize(450, 300);
        //this.setResizable(false);
        this.addWindowListener(this);
    }

    /*======================================
      Implement WindowListener interfaces
      ======================================*/
    public void windowOpened( WindowEvent evt ){ }
    public void windowClosed( WindowEvent evt ){ }
    public void windowIconified( WindowEvent evt ){ }
    public void windowDeiconified( WindowEvent evt ){ }
    public void windowActivated( WindowEvent evt ){ update(); }
    public void windowDeactivated( WindowEvent evt ){ }
    public void windowClosing( WindowEvent evt ){ if (save()) hide(); }

    private void update() {
        if (iBlockUpdate > 0)
            // We are blocked at least once. Decrease block counter
            iBlockUpdate--;
        else if (tabPaths.iBlockUpdate > 0)
            tabPaths.iBlockUpdate--;
        else {
            // tab "Zone Display"
            updateTabZoneDisplay();

            // tab "Zone Buffers"
            // tab "Paths"
            tabPaths.update();

            // tab "Project"
            // tab "Scale"
            updateTabScale();

            // tab "Status Bar"

            // tab "Misc"
        }
    }

    public void setActiveTab(int activeTab) {
        if (activeTab != TAB_DEFAULT)
            tabbedPane.setSelectedIndex(activeTab);
    }

    public void actionPerformed(ActionEvent evt) {
        Object o = evt.getSource();

        if (o == btnOk) {
            if (save())
                hide();
        } else if (o == btnCancel) {
            hide();
        }
    }

    private final void renameCancelButton() {
        btnCancel.setText("Close");
    }

    private boolean save() {
        try {
            // tab "Zone Display"
            saveTabZoneDisplay();

            // tab "Zone Buffers"
            // tab "Paths"
            tabPaths.save();

            // tab "Project"
            // tab "Scale"
            saveTabScale();

            // tab "Status Bar"

            // tab "Misc"
            if (SysConst.DEBUG_MODE >= 2)
                saveTabMisc();

            return true;
        } catch(Exception e) {
            JOptionPane.showMessageDialog(this,
                "Error Occured.  Please check data format.");
            return false;
        }
    }


    /*
     * tab "Zone Display"
     */
    private JPanel createTabZoneDisplay(){
        JPanel panel = new JPanel(gridBagLayout);

        vZoneData = new Vector();
        modelZone = new ZoneTableModel();
        tblZone = new JTable(modelZone);
        tblZone.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
        tblZone.setDefaultRenderer(Color.class, new ColorRenderer());
        tblZone.setDefaultEditor(Color.class, new ColorEditor());
        tblZone.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        add(panel, new JScrollPane(tblZone), 0, 0, 4, 1, 100, 100,
            GridBagConstraints.CENTER, GridBagConstraints.BOTH,
            GAP, GAP, GAP, GAP);

        btnRemoveZones = new JButton("Clean up Zones");
        btnRemoveZones.setMnemonic('C');
        btnRemoveZones.addActionListener(alTabZoneDisplay);
        btnRefreshScreen = new JButton("Refresh Screen");
        btnRefreshScreen.setMnemonic('R');
        btnRefreshScreen.addActionListener(alTabZoneDisplay);
        btnZoneUp = new JButton("Up");
        btnZoneUp.setMnemonic('U');
        btnZoneUp.addActionListener(alTabZoneDisplay);
        btnZoneDown = new JButton("Down");
        btnZoneDown.setMnemonic('D');
        btnZoneDown.addActionListener(alTabZoneDisplay);

        add(panel, btnRemoveZones, 0, 1, 1, 1, 0, 0,
            GridBagConstraints.CENTER, GridBagConstraints.NONE, 0, GAP, GAP, 0);
        add(panel, btnRefreshScreen, 1, 1, 1, 1, 100, 0,
            GridBagConstraints.CENTER, GridBagConstraints.NONE, 0, GAP, GAP, 0);
        add(panel, btnZoneUp, 2, 1, 1, 1, 0, 0,
            GridBagConstraints.CENTER, GridBagConstraints.NONE, 0, GAP, GAP, 0);
        add(panel, btnZoneDown, 3, 1, 1, 1, 0, 0,
            GridBagConstraints.CENTER, GridBagConstraints.NONE, 0, GAP,GAP,GAP);

        return panel;
    }

    private void updateTabZoneDisplay(){
        int iZoneCount = Sys.prjInfo.allZone.size();
        if (vZoneData.size() < iZoneCount) {
            vZoneData.ensureCapacity(iZoneCount);
            NumberFormat nf = NumberFormat.getNumberInstance();
            nf.setGroupingUsed(false);
            for (int i = vZoneData.size(); i < iZoneCount; i++) {
                Zone z = (Zone)Sys.prjInfo.allZone.elementAt(i);

                Object[] zoneData = new Object[4];
                zoneData[0] = "Zone " + nf.format(z.getZoneNumber());
                zoneData[1] = z.getZoneColor();
                zoneData[2] = z.getZoneLabel();
                zoneData[3] = new Double(z.getZoneNumber());
                vZoneData.addElement(zoneData);
            }
            int row = tblZone.getSelectedRow();
            int col = tblZone.getSelectedColumn();
            modelZone.fireTableDataChanged();
            tblZone.changeSelection((row >= 0 ? row : 0), col, false, false);
        }
    }

    private ActionListener alTabZoneDisplay = new ActionListener() {
        public void actionPerformed(ActionEvent evt){
            Object o = evt.getSource();

            if (o == btnRefreshScreen) {
                saveTabZoneDisplay();
            } else if (o == btnZoneUp) {
                int index = tblZone.getSelectedRow();
                if (index >= 1) {
                    Object[] zoneData = (Object[])vZoneData.elementAt(index);
                    vZoneData.setElementAt(vZoneData.elementAt(index-1), index);
                    vZoneData.setElementAt(zoneData, index-1);
                    modelZone.fireTableRowsUpdated(index-1, index);
                    tblZone.changeSelection(index-1,
                        tblZone.getSelectedColumn(), false, false);
                }
            } else if (o == btnZoneDown) {
                int index = tblZone.getSelectedRow();
                if (index >= 0 && index < vZoneData.size()-1) {
                    Object[] zoneData = (Object[])vZoneData.elementAt(index);
                    vZoneData.setElementAt(vZoneData.elementAt(index+1), index);
                    vZoneData.setElementAt(zoneData, index+1);
                    modelZone.fireTableRowsUpdated(index, index+1);
                    tblZone.changeSelection(index+1,
                        tblZone.getSelectedColumn(), false, false);
                }
            } else if (o == btnRemoveZones) {
                int elemSize = Sys.elemList.size();
                int templSize = Templates.allList.size();
                int idxElem;
                for (int idxZone = 0; idxZone < vZoneData.size(); idxZone++) {
                    Object[] zoneData = (Object[])vZoneData.elementAt(idxZone);
                    double dZone = ((Double)zoneData[3]).doubleValue();

                    // Check elements
                    for (idxElem = 0; idxElem < elemSize; idxElem++) {
                        AbsElem elem = (AbsElem)Sys.elemList.elementAt(idxElem);
                        if (dZone ==
                                elem.getData(AbsElem.DATA_ZONE))
                            break;
                    }
                    if (idxElem < elemSize)
                        continue; // Zone was found

                    // Check templates
                    for (idxElem = 0; idxElem < templSize; idxElem++) {
                        AbsElem elem = (AbsElem)Templates.allList.
                            elementAt(idxElem);
                        if (dZone ==
                                elem.getData(AbsElem.DATA_ZONE))
                            break;
                    }
                    if (idxElem < templSize)
                        continue; // Zone was found

                    // Zone was not found, remove it
                    vZoneData.removeElementAt(idxZone);
                    // We deleted the idxZone-th element, so we have to continue
                    // again with the idxZone-th element to get the next one.
                    idxZone--;
                }
                int row = tblZone.getSelectedRow();
                int col = tblZone.getSelectedColumn();
                if (row < 0) { row = 0; }
                else if (row >= vZoneData.size()) { row = vZoneData.size()-1; }
                modelZone.fireTableDataChanged();
                tblZone.changeSelection(row, col, false, false);

                saveTabZoneDisplay();
            }
        }
    };

    private void saveTabZoneDisplay() {
        // If I'm currently editing,
        // then I should save the value and stop editing
        if (tblZone.isEditing())
            tblZone.getCellEditor().stopCellEditing();

        int iZoneCount = vZoneData.size();
        Sys.prjInfo.allZone.setSize(iZoneCount);
        for (int i = 0; i < iZoneCount; i++) {
            Zone z = (Zone)Sys.prjInfo.allZone.elementAt(i);

            Object[] zoneData = (Object[])vZoneData.elementAt(i);
            z.setZoneNumber(((Double)zoneData[3]).doubleValue());
            z.setZoneColor((Color)zoneData[1]);
            z.setZoneLabel((String)zoneData[2]);
        }
        renameCancelButton();
        mainFrame.mainPanel.needRedraw = true;
        mainFrame.mainPanel.repaint();
    }

    private class ZoneTableModel extends AbstractTableModel {
        final String[] columnNames = { "Number", "Color", "Label" };

        public int getColumnCount() { return columnNames.length; }
        public int getRowCount() { return vZoneData.size(); }
        public String getColumnName(int col) { return columnNames[col]; }
        public Object getValueAt(int row, int col) {
            return ((Object[])vZoneData.elementAt(row))[col];
        }

        public Class getColumnClass(int col) {
            return (col == 1 ? Color.class : String.class);
        }

        public boolean isCellEditable(int row, int col) {
            // Note that the data/cell address is constant,
            // no matter where the cell appears onscreen.
            return (col >= 1);
        }

        public void setValueAt(Object value, int row, int col) {
            ((Object[])vZoneData.elementAt(row))[col] = value;
            fireTableCellUpdated(row, col);
        }
    }

    class ColorRenderer extends JLabel implements TableCellRenderer {
        Border focusBorder = BorderFactory.createLineBorder(Color.yellow);

        public ColorRenderer() {
            setOpaque(true); // MUST do this for background to show up.
        }

        public Component getTableCellRendererComponent(JTable table,
            Object color, boolean isSelected, boolean hasFocus,
            int row, int column) {

            setBackground((Color)color);
            setBorder((isSelected && hasFocus) ? focusBorder : null);
            return this;
        }
    }

    class ColorEditor extends DefaultCellEditor {
        Color currentColor = null;

        public ColorEditor() {
            // Unfortunately, the constructor expects a check box,
            // combo box, or text field.
            super(new JCheckBox());

            JButton button = new JButton("");
            button.setBorderPainted(false);
            button.setMargin(new Insets(0, 0, 0, 0));
            button.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    iBlockUpdate++; // Increase block counter
                    Color c = JColorChooser.showDialog(editorComponent,
                        "Choose a Color", currentColor);
                    if (c != null)
                        currentColor = c;
                    // Must do this so that editing stops when appropriate.
                    fireEditingStopped();
                }
            });
            editorComponent = button;
        }

        public Object getCellEditorValue() { return currentColor; }

        public Component getTableCellEditorComponent(JTable table, Object value,
            boolean isSelected, int row, int column) {
            currentColor = (Color)value;
            ((JButton)editorComponent).setBackground(currentColor);
            return editorComponent;
        }
    }

    /*
     * tab "Zone Buffers"
     */
    private JPanel createTabZoneBuffers(){
        JPanel panel = new JPanel();
        return panel;
    }

    /*
     * tab "Paths"
     */
    public static class PathsPanel extends JPanel implements ActionListener {
        private int iBlockUpdate = 0;

        private File[][] fPaths;
        private JTextField[][] tfPaths;
        private JButton[][] btnPaths;

        public PathsPanel() {
            super(gridBagLayout);

            // Initialize things that are different
            final String[] asPanelCaption = { " Paths ", " Files " };
            final String[][] asLabelPath = {
                { "Project Files:", "Temporary Files:" },
                { "Microsoft Excel:" }
            };
            fPaths = new File[2][];
            fPaths[0] = new File[PersonalInfo.MAX_PATH];
            fPaths[1] = new File[PersonalInfo.MAX_EXT_FILE];
            tfPaths = new JTextField[2][];
            btnPaths = new JButton[2][];

            // Construct panels
            GridBagConstraints gbc = new GridBagConstraints(0, 0, 1, 1, 0, 0,
                GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL,
                new Insets(0, GAP, 0, GAP), 0, 0);

            JPanel[] subPanel = new JPanel[2];
            for (int iPanel = 0; iPanel < 2; iPanel++) {
                subPanel[iPanel] = new JPanel(gridBagLayout);
                subPanel[iPanel].setBorder(BorderFactory.createTitledBorder(
                    BorderFactory.createEtchedBorder(),asPanelCaption[iPanel]));
                gbc.gridx = 0;
                gbc.gridy = iPanel;
                gbc.weightx = 100;
                gbc.weighty = (iPanel == 1 ? 100 : 0);
                gbc.anchor = GridBagConstraints.NORTH;
                gbc.insets.top = GAP;
                add(subPanel[iPanel], gbc);

                // Initialize things that are common
                gbc.weightx = gbc.weighty = 0;
                gbc.insets.top = 0;
                int iCount = fPaths[iPanel].length;
                tfPaths[iPanel] = new JTextField[iCount];
                btnPaths[iPanel] = new JButton[iCount];
                for (int i = 0; i < iCount; i++) {
                    tfPaths[iPanel][i] = new JTextField();
                    tfPaths[iPanel][i].setEditable(false);
                    tfPaths[iPanel][i].setHorizontalAlignment(JTextField.LEADING);
                    btnPaths[iPanel][i] = new JButton("...");
                    btnPaths[iPanel][i].addActionListener(this);
                    JLabel label = new JLabel(asLabelPath[iPanel][i]);
                    label.setDisplayedMnemonic(asLabelPath[iPanel][i].charAt(0));
                    label.setLabelFor(btnPaths[iPanel][i]);

                    // Construct path panel
                    gbc.gridx = 0;
                    gbc.gridy = i;
                    gbc.anchor = GridBagConstraints.WEST;
                    gbc.fill = GridBagConstraints.NONE;
                    gbc.insets.bottom = (i == iCount-1 ? GAP : 0);
                    gbc.insets.right = 0;
                    subPanel[iPanel].add(label, gbc);

                    gbc.gridx = 1;
                    gbc.weightx = 100;
                    gbc.fill = GridBagConstraints.HORIZONTAL;
                    subPanel[iPanel].add(tfPaths[iPanel][i], gbc);

                    gbc.gridx = 2;
                    gbc.weightx = 0;
                    gbc.insets.right = GAP;
                    subPanel[iPanel].add(btnPaths[iPanel][i], gbc);
                }
            }

            update();
        }

        public void update() {
            // update paths
            for (int i = 0; i < PersonalInfo.MAX_PATH; i++)
                fPaths[0][i] = Sys.personalInfo.getPath(i);
            for (int i = 0; i < PersonalInfo.MAX_EXT_FILE; i++)
                fPaths[1][i] = Sys.personalInfo.getExtFile(i);

            // update text fields
            for (int iPanel = 0; iPanel < 2; iPanel++)
                for (int i = 0; i < fPaths[iPanel].length; i++)
                    tfPaths[iPanel][i].setText(fPaths[iPanel][i].getPath());
        }

        public void actionPerformed(ActionEvent evt) {
            Object o = evt.getSource();

            for (int i = 0; i < btnPaths[0].length; i++) {
                if (o == btnPaths[0][i]) {
                    JFileChooser chooser = new JFileChooser();
                    chooser.setAcceptAllFileFilterUsed(false);
                    chooser.setDialogTitle("Choose a path");
                    chooser.setFileFilter(new FileFilter() {
                        public boolean accept(File f) {
                            return f.isDirectory();
                        }
                        public String getDescription() {
                            return "All directories";
                        }
                    });
                    chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
                    chooser.setSelectedFile(Sys.personalInfo.getPath(i));
                    iBlockUpdate++; // Increase block counter
                    if (chooser.showDialog(this, "Ok") ==
                        JFileChooser.APPROVE_OPTION) {
                        fPaths[0][i] = chooser.getSelectedFile();
                        tfPaths[0][i].setText(fPaths[0][i].getPath());
                    }
                }
            }
            for (int i = 0; i < btnPaths[1].length; i++) {
                if (o == btnPaths[1][i]) {
                    JFileChooser chooser = new JFileChooser();
                    chooser.setAcceptAllFileFilterUsed(true);
                    chooser.setDialogTitle("Choose a file");
                    chooser.setFileFilter(new FileFilter() {
                        public boolean accept(File f) {
                            return f.isDirectory() ||
                                f.getName().toLowerCase().endsWith(".exe");
                        }
                        public String getDescription() {
                            return "All Executables (*.exe)";
                        }
                    });
                    chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
                    chooser.setSelectedFile(Sys.personalInfo.getExtFile(i));
                    iBlockUpdate++; // Increase block counter
                    if (chooser.showDialog(this, "Ok") ==
                        JFileChooser.APPROVE_OPTION) {
                        fPaths[1][i] = chooser.getSelectedFile();
                        tfPaths[1][i].setText(fPaths[1][i].getPath());
                    }
                }
            }
        }

        public void save() {
            for (int i = 0; i < PersonalInfo.MAX_PATH; i++)
                Sys.personalInfo.setPath(i, fPaths[0][i]);
            for (int i = 0; i < PersonalInfo.MAX_EXT_FILE; i++)
                Sys.personalInfo.setExtFile(i, fPaths[1][i]);
        }
    };

    /*
     * tab "Project"
     */
    private JPanel createTabProject(){
        JPanel panel = new JPanel();
        return panel;
    }

    /*
     * tab "Scale"
     */
    private JPanel createTabScale(){
        JPanel panel = new JPanel();
        JPanel firstPanel  = new JPanel(new GridLayout(3,1));
        JPanel secondPanel = new JPanel(new GridLayout(4,1));
        JPanel thirdPanel  = new JPanel(new GridLayout(2,1));
        JPanel fourthPanel = new JPanel(new GridLayout(2,1));

        JLabel lblOne = new JLabel("Scale Bar Length");
        lblOne.setForeground(Color.blue);
        ScaleBarPanel sbp = new ScaleBarPanel();
        tfScale = new JTextField(8);
        tfScale.setInputVerifier( new DoubleVerifier());

        firstPanel.add(lblOne);
        firstPanel.add(sbp);
        firstPanel.add(tfScale);

        ButtonGroup bg= new ButtonGroup();
        rbs= new JRadioButton[4];
        rbs[0]= new JRadioButton("Miles");
        rbs[1]= new JRadioButton("Kilometers");
        rbs[2]= new JRadioButton("Kilofeet");
        rbs[3]= new JRadioButton("Feet");
        for(int i=0;i<4;i++){
            bg.add(rbs[i]);
            secondPanel.add(rbs[i]);
        }

        JLabel lblTwo=new JLabel("Grid Spacing");
        lblTwo.setForeground(Color.blue);
        tfGridSpacing = new JTextField(8);
        tfGridSpacing.setInputVerifier( new DoubleVerifier());
        tfGridSpacing.setEnabled(false);
        thirdPanel.add(lblTwo);
        thirdPanel.add(tfGridSpacing);

        btnAccept = new JButton("Accept");
        fourthPanel.add( new JLabel("")); //dummy label
        fourthPanel.add(btnAccept);

        GridBagConstraints c = new GridBagConstraints();
        c.insets = new Insets(5,5,5,5);
        c.fill = GridBagConstraints.BOTH;
        c.anchor = GridBagConstraints.WEST;
        panel.setLayout(gridBagLayout);

        JPanel top = new JPanel( new GridLayout(1,2,20,0) );
        top.setBorder( new TitledBorder("") );
        top.add( firstPanel );
        top.add( secondPanel );
        JPanel btm = new JPanel( new GridLayout(1,2, 20,0) );
        btm.setBorder( new TitledBorder("") );
        btm.add( thirdPanel );
        btm.add( fourthPanel );

        c.gridx=0; c.gridy=0; panel.add(top,c);
        c.gridx=0; c.gridy=1; panel.add(btm,c);

//        c.gridx=0; c.gridy=0; c.gridheight=2; panel.add(firstPanel,c);
//        c.gridx=1; c.gridy=0; c.gridheight=2; panel.add(secondPanel,c);
//        c.gridx=0; c.gridy=2; c.gridheight=1; panel.add(thirdPanel,c);
//        c.gridx=1; c.gridy=2; c.gridheight=1; panel.add(fourthPanel,c);

        btnAccept.addActionListener(alTabScale);
        for(int i=0;i<4;i++){ rbs[i].addActionListener(alTabScale); }

        return panel;
    }

    private void updateTabScale() {
        // virtual resolution = (SysConst.SCALEBAR_LENGTH/Sys.gridWidth)
        double currScale = Sys.prjInfo.lengthPerUnit*(SysConst.SCALEBAR_LENGTH/Sys.prjInfo.dZoomFactor);
        NumberFormat nf = NumberFormat.getNumberInstance();
        nf.setMaximumFractionDigits(5);
        nf.setGroupingUsed(false);
        String sCurrScale = nf.format(currScale);
        tfScale.setText(sCurrScale);
        tfGridSpacing.setText(sCurrScale);
        rbs[Sys.prjInfo.unitOfLength].setSelected(true);
    }

    ActionListener alTabScale = new ActionListener(){
        public void actionPerformed(ActionEvent evt){
            Object o = evt.getSource();
            if (o == btnAccept) {
                saveTabScale();
                mainFrame.mainPanel.repaint();
            } else {
                for (int i = 0; i < 4; i++) {
                    if (o == rbs[i]){ //select unit only change the text in tfScale
                        int j = Sys.prjInfo.unitOfLength;
                        double ratio = Sys.findRatioBtwnUnits(i, j);

                        NumberFormat nf = NumberFormat.getNumberInstance();
                        nf.setMaximumFractionDigits(5);
                        nf.setGroupingUsed(false);
                        double currScale = Sys.prjInfo.lengthPerUnit*(SysConst.SCALEBAR_LENGTH/Sys.prjInfo.dZoomFactor);
                        tfScale.setText(nf.format(currScale * ratio));
                        //JOptionPane.showMessageDialog(mainFrame,""+i);
                        break;
                    }
                }
            }
        }
    };

    private void saveTabScale() {
        int prevUnit = Sys.prjInfo.unitOfLength;
        for (int i = 0; i < 4; i++) {
            if (rbs[i].isSelected()) {
                Sys.prjInfo.unitOfLength = i;
                break;
            }
        }
        int currUnit = Sys.prjInfo.unitOfLength;
        // virtual resolution = (SysConst.SCALEBAR_LENGTH/Sys.MapSF)
        double prevScale = Sys.prjInfo.lengthPerUnit
            *(SysConst.SCALEBAR_LENGTH/Sys.prjInfo.dZoomFactor);
        double currScale = Double.parseDouble(tfScale.getText());
        Sys.prjInfo.lengthPerUnit =
            currScale/(SysConst.SCALEBAR_LENGTH/Sys.prjInfo.dZoomFactor);

        tfGridSpacing.setText(tfScale.getText());

        Sys.multiplyLengthForAllElem( currScale/prevScale );
        if( currUnit != prevUnit){ //only when unit changed
            double k = Sys.findRatioBtwnUnits(currUnit, prevUnit);
            Sys.divideDataInPerUnitForAllElem(k);
            Templates.divideDataInPerUnitForAllTmplt(k);
        }
        renameCancelButton();
    }

    /*
     * tab "Status Bar"
     */
    private JPanel createTabStatusBar(){
        JPanel panel = new JPanel();
        return panel;
    }

    /*
     * tab "Misc"
     */
    private JPanel createTabMisc(){
        JPanel panel = new JPanel(gridBagLayout);

        JPanel panelLookAndFeel = new JPanel(gridBagLayout);
        panelLookAndFeel.setBorder(BorderFactory.createTitledBorder(
            BorderFactory.createEtchedBorder(), " Look 'n' Feel "));
        add(panel, panelLookAndFeel, 0, 0, 1, 1, 100, 100,
            GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL,
            GAP, GAP, GAP, GAP);

        // initialize components
        comboLookAndFeel = new JComboBox();
        UIManager.LookAndFeelInfo[] aLAFI = UIManager.getInstalledLookAndFeels();
        String sClassName = Sys.personalInfo.getLookAndFeelClassName();
        for (int i = 0; i < aLAFI.length; i++) {
            String sName = aLAFI[i].getName();
            comboLookAndFeel.addItem(sName);
            if (sClassName.equals(aLAFI[i].getClassName()))
                comboLookAndFeel.setSelectedItem(sName);
        }
        JLabel lblLookAndFeel = new JLabel("Name:");
        lblLookAndFeel.setDisplayedMnemonic('N');
        lblLookAndFeel.setLabelFor(comboLookAndFeel);

        add(panelLookAndFeel, lblLookAndFeel, 0, 0, 1, 1, 0, 0,
            GridBagConstraints.CENTER, GridBagConstraints.NONE, 0, GAP, GAP, 0);
        add(panelLookAndFeel, comboLookAndFeel, 1, 0, 1, 1, 100, 0,
            GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
            0, GAP, GAP, GAP);

        return panel;
    }

    private void saveTabMisc() {
        int index = comboLookAndFeel.getSelectedIndex();
        if (index >= 0) {
            String sNewClassName =
                UIManager.getInstalledLookAndFeels()[index].getClassName();
            if (!sNewClassName.equals(
                    Sys.personalInfo.getLookAndFeelClassName())) {
                Sys.personalInfo.setLookAndFeelClassName(sNewClassName);
                JOptionPane.showMessageDialog(this,
                    "You need to restart iPAD to see the new Look 'n' Feel.");
            }
        }
    }
}//end of class OptionsDlg;

class ScaleBarPanel extends JPanel{
    public void paintComponent(Graphics g){
        Color oldColor = g.getColor();
        for(int i=0;i<4;i++){
            if( (i%2) == 0){
                g.setColor( Color.gray);
                g.fillRect( 16*i, 0, 16, 10);
            }
            g.setColor( Color.black);
            g.drawRect( 16*i, 0, 16, 10);
        }
        g.setColor( oldColor);
    }
}


